#ifndef MAPTILES_H_
#define MAPTILES_H_

#include "Map.h"
#include "Geo.h"

namespace opennav {

class Map;

struct MapTileHeader {
	int32_t zoom_table_offset;
	uint8_t zoom_table_size;
	int32_t map_tile_def_table_offset;
	uint16_t map_tile_def_table_size;
	int32_t map_tile_table_offset;
};

struct Zoom {
	uint8_t resolution;
	uint16_t tiles;
	uint8_t zoom_level;
	uint8_t shift() const { return 24 - resolution; }
};

struct MapTileDef {
	uint16_t tile_id;
	int32_t tile_offset;
	uint16_t first_subtile_id;
	bool last;
	Zoom zoom;
	Area bounds;
	Coordinate center;
};

enum MapObjectType {
	UNKNOWN = 0,
	SHAPE = 1,
	LINE = 2,
	POINT = 3
};

struct MapObjectReference {
	uint16_t tile_id;
	int16_t object_id;
	bool operator==(const MapObjectReference &other) const {
		return ( (other.tile_id == tile_id) &&
				(other.object_id == object_id) );
	}
};

struct MapObject {
	virtual MapObjectType type() const = 0;
	Map* map;
	Area bounds;
	MapObjectReference map_object_ref;
};

struct MapLine : public MapObject {
	MapObjectType type() const { return LINE; }
	int16_t line_type;
	int32_t reference;
	std::vector<Coordinate> coordinates;
	bool road;
};

struct MapPoint : public MapObject {
	MapObjectType type() const { return POINT; }
	int16_t point_type;
	int32_t reference;
	Coordinate coordinate;
	bool poi;
};

struct MapShape : public MapObject {
	MapObjectType type() const { return SHAPE; }
	int16_t shape_type;
	int32_t reference;
	std::vector<Coordinate> coordinates;
};

const static int16_t Line_Motorway = 0x0001;
const static int16_t Line_Highway1 = 0x0002;
const static int16_t Line_Highway2 = 0x0003;
const static int16_t Line_Highway3 = 0x0004;
const static int16_t Line_Highway4 = 0x0005;
const static int16_t Line_Highway5 = 0x0006;
const static int16_t Line_Track = 0x0007;
const static int16_t Line_Rail = 0x0008;
const static int16_t Line_Tram = 0x0009;
const static int16_t Line_Subway = 0x000a;
const static int16_t Line_Monorail = 0x000b;
const static int16_t Line_Funicular = 0x000c;
const static int16_t Line_River = 0x000d;
const static int16_t Line_Stream = 0x000e;
const static int16_t Line_Weir = 0x000f;
const static int16_t Line_Raceway = 0x0010;
const static int16_t Line_Coast = 0x0011;
const static int16_t Line_BorderCountry = 0x0012;
const static int16_t Shape_River = 0x0001;
const static int16_t Shape_Lake = 0x0002;
const static int16_t Shape_Wetland = 0x0003;
const static int16_t Shape_Residential = 0x0004;
const static int16_t Shape_Industrial = 0x0005;
const static int16_t Shape_Military = 0x0006;
const static int16_t Shape_Cemetary = 0x0007;
const static int16_t Shape_Shopping = 0x0008;
const static int16_t Shape_Farming = 0x0009;
const static int16_t Shape_Forest = 0x000a;
const static int16_t Shape_Grass = 0x000b;
const static int16_t Shape_Cultivation = 0x000c;
const static int16_t Shape_Recreation = 0x000d;
const static int16_t Shape_Glacier = 0x000e;
const static int16_t Shape_Dam = 0x000f;
const static int16_t Shape_Beach = 0x0010;
const static int16_t Shape_Building = 0x0011;
const static int16_t Point_City1 = 0x0001;
const static int16_t Point_City2 = 0x0002;
const static int16_t Point_City3 = 0x0003;
const static int16_t Point_City4 = 0x0004;
const static int16_t Point_Suburb = 0x0005;

}

#endif /* MAPTILES_H_ */
